package database

import (
	"fmt"
	"go-caipu/pkg/install/dto"
	"gorm.io/driver/postgres"
	"os"
	"path"
	"path/filepath"
	"strings"

	"github.com/glebarez/sqlite"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var DB *gorm.DB

// InitDB 初始化数据库连接
func InitDB(set dto.Database) error {
	var db *gorm.DB
	var err error
	switch set.Type {
	case "sqlite":
		db, err = initSQLite(path.Join("./data/", set.SQLite.Path))
	case "mysql":
		dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/?charset=utf8mb4&parseTime=True&loc=Local", set.Username, set.Password, set.Host, set.Port)
		db, err = initMySQL(dsn)
	case "postgresql":
		dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Shanghai", set.Host, set.Username, set.Password, set.DbName, set.Port)
		db, err = initPostgreSQL(dsn)
	default:
		return fmt.Errorf("不支持的数据库类型: %s", set.Type)
	}
	if err != nil {
		return err
	}
	DB = db
	return nil
}

// initSQLite 初始化SQLite数据库连接
func initSQLite(dsn string) (*gorm.DB, error) {
	// 确保目录存在
	if strings.HasPrefix(dsn, "file:") {
		filePath := strings.TrimPrefix(dsn, "file:")
		dir := filepath.Dir(filePath)
		if err := os.MkdirAll(dir, 0755); err != nil {
			return nil, fmt.Errorf("创建SQLite目录失败: %v", err)
		}
	}

	// 连接SQLite数据库
	db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{})
	if err != nil {
		return nil, fmt.Errorf("连接SQLite数据库失败: %v", err)
	}

	return db, nil
}

// initMySQL 初始化MySQL数据库连接
func initMySQL(dsn string) (*gorm.DB, error) {
	// 连接数据库
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		return nil, fmt.Errorf("连接MySQL数据库失败: %v", err)
	}

	// 设置连接池
	sqlDB, err := db.DB()
	if err != nil {
		return nil, err
	}
	// 设置最大空闲连接数
	sqlDB.SetMaxIdleConns(10)
	// 设置最大打开连接数
	sqlDB.SetMaxOpenConns(100)

	return db, nil
}

// initPostgreSQL 初始化PostgreSQL数据库连接
func initPostgreSQL(dsn string) (*gorm.DB, error) {
	// 连接数据库
	db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
	if err != nil {
		return nil, fmt.Errorf("连接PostgreSQL数据库失败: %v", err)
	}

	// 设置连接池
	sqlDB, err := db.DB()
	if err != nil {
		return nil, err
	}

	// 设置最大空闲连接数
	sqlDB.SetMaxIdleConns(10)
	// 设置最大打开连接数
	sqlDB.SetMaxOpenConns(100)

	return db, nil
}

// CreateDatabase 创建数据库
func CreateDatabase(db dto.Database) error {

	switch db.Type {
	case "sqlite":
		return createSQLiteDatabase(path.Join("./data/", db.SQLite.Path))
	case "mysql":
		dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/?charset=utf8mb4&parseTime=True&loc=Local", db.Username, db.Password, db.Host, db.Port)
		return createMySQLDatabase(dsn, db.DbName)
	case "postgresql":
		dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Shanghai", db.Host, db.Username, db.Password, db.DbName, db.Port)
		return createPostgreSQLDatabase(dsn)
	default:
		return fmt.Errorf("不支持的数据库类型: %s", db.Type)
	}
}

// createSQLiteDatabase 创建SQLite数据库文件
func createSQLiteDatabase(dsn string) error {
	// 确保目录存在
	if strings.HasPrefix(dsn, "file:") {
		filePath := strings.TrimPrefix(dsn, "file:")
		dir := filepath.Dir(filePath)
		if err := os.MkdirAll(dir, 0755); err != nil {
			return fmt.Errorf("创建SQLite目录失败: %v", err)
		}
	}

	// SQLite数据库文件会在首次连接时自动创建
	// 这里只需要确保目录存在即可
	return nil
}

// createMySQLDatabase 创建MySQL数据库
func createMySQLDatabase(dsn string, dbname string) error {
	// 解析DSN获取数据库名
	// 对于MySQL DSN格式：username:password@tcp(host:port)/dbname?params
	//parts := strings.Split(dsn, "/")
	//if len(parts) < 2 {
	//	return fmt.Errorf("无效的MySQL DSN格式")
	//}
	//
	//dbnamePart := strings.Split(parts[1], "?")[0]
	//if dbnamePart == "" {
	//	return fmt.Errorf("未指定数据库名")
	//}
	//
	//// 构建连接系统数据库的DSN（不指定数据库名）
	//systemDSN := strings.Replace(dsn, "/"+dbnamePart, "/", 1)
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		return err
	}

	// 创建数据库
	sqlDB, _ := db.DB()
	defer sqlDB.Close()

	// 检查数据库是否存在
	var exists bool
	row := sqlDB.QueryRow("SELECT COUNT(*) FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = ?", dbname)
	row.Scan(&exists)

	if !exists {
		// 创建数据库
		_, err := sqlDB.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS `%s` DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci", dbname))
		if err != nil {
			return err
		}
	}

	return nil
}

// createPostgreSQLDatabase 创建PostgreSQL数据库
func createPostgreSQLDatabase(dsn string) error {
	// 对于PostgreSQL，数据库创建需要连接postgres数据库
	// 解析DSN获取数据库名
	parts := strings.Split(dsn, "dbname=")
	if len(parts) < 2 {
		return fmt.Errorf("无效的PostgreSQL DSN格式")
	}

	dbnamePart := strings.Split(parts[1], " ")[0]
	if dbnamePart == "" {
		return fmt.Errorf("未指定数据库名")
	}

	// 构建连接postgres数据库的DSN
	systemDSN := strings.Replace(dsn, "dbname="+dbnamePart, "dbname=postgres", 1)

	db, err := gorm.Open(postgres.Open(systemDSN), &gorm.Config{})
	if err != nil {
		return err
	}

	// 创建数据库
	sqlDB, _ := db.DB()
	defer sqlDB.Close()

	// 检查数据库是否存在
	var exists bool
	row := sqlDB.QueryRow("SELECT COUNT(*) FROM pg_database WHERE datname = $1", dbnamePart)
	row.Scan(&exists)

	if !exists {
		// 创建数据库
		_, err := sqlDB.Exec(fmt.Sprintf("CREATE DATABASE %s", dbnamePart))
		if err != nil {
			return err
		}
	}

	return nil
}
